#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>

#define MAX_USR_NAME_LEN 	20
#define MAX_BUFFER_SIZE	 	1024
#define TIMEOUT_SEC	 	300
#define oops(msg) 		{printf("client: "); perror(msg); exit(1);}

int main(int ac, char *av[])
{
	struct sockaddr_in	server_addr;
	int 			sock_fd;
	int			usr_name_len;
	char	 		buffer[MAX_USR_NAME_LEN];

	//socket init	
	if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
		oops("socket");
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = inet_addr(av[1]);
	server_addr.sin_port = htons(atoi(av[2]));
	
	if (connect(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
		oops("connect");

	//input user name and send to server	
	while (true)
	{
		printf("> enter your name > ");
		fflush(stdout);
		if ((usr_name_len = read(0, buffer, MAX_BUFFER_SIZE)) < 0)
			oops("read");			
		if (usr_name_len < MAX_USR_NAME_LEN -1)
			break;
		printf("> name's length too long\n");
	}	
	if (write(sock_fd, buffer, usr_name_len - 1) < 0)//remove '-r' at the end of string
		oops("write");
	
	//main loop: wait either from stdin or server 
	struct timeval		timeout;
	int			stdin_fd = 0;
	int			stdout_fd = 1;
	int 			max_fd;
	int			len;
	int 			select_ret;
	fd_set			read_fds;

	FD_ZERO(&read_fds);
	FD_SET(stdin_fd, &read_fds);
	FD_SET(sock_fd, &read_fds);
	max_fd = (stdin_fd > sock_fd ? stdin_fd + 1 : sock_fd + 1);

	timeout.tv_sec = TIMEOUT_SEC;
	timeout.tv_usec = 0;
	
	while (true)
	{
		if ((select_ret = select(max_fd, &read_fds, NULL, NULL, &timeout)) < 0)
			oops("select");
		if (select_ret == 0)		//time out
		{
			if (write(sock_fd, buffer, MAX_BUFFER_SIZE) < 0)
				oops("write");
			break;
		}
		if (FD_ISSET(stdin_fd, &read_fds))	//read from stdin
		{
			if ((len = read(stdin_fd, buffer, MAX_BUFFER_SIZE)) < 0)
				oops("read");
			if (len == 0)
				break;
			buffer[len] = '\0';
			if (write(sock_fd, buffer, len) < 0)
				oops("write");
		}
		if (FD_ISSET(sock_fd, &read_fds))	//read from server
		{
			if ((len = read(sock_fd, buffer, MAX_BUFFER_SIZE)) < 0)
				oops("read");
			if (len == 0)
			{
				printf("> connection closed by server\n");
				break;
			}
			else
			{
				printf("> ");
				fflush(stdout);
				if (write(stdout_fd, buffer, len) < 0)
					oops("write");
			}
		}

		FD_SET(stdin_fd, &read_fds);
		FD_SET(sock_fd, &read_fds);
	}
	
	close(sock_fd);
	return 0;
}





